页面效果:
主要解决两个问题:
- 组件的拖拽;
- 渲染组件 component 和样式修改组件 styleComponent 数据流转问题。
# 组件的拖拽和克隆
组件拖拽这里使用到的是这个基于 sortable.js (opens new window),使用 Vue 进行封装的组件 Vue.Draggable (opens new window)。具体使用官方文档和相关例子都很详细。
主要使用两个功能:
- 拖拽:更改页面布局
- 克隆:将左边渲染组件列表中的组件拖拽克隆到中间页面预览区域
# 拖拽
h5-editor 组件使用方式:
<h5-editor v-model="jsonData" :data="data"></h5-editor>
<template>
<draggable
class="dragArea list-group"
v-model="layout"
tag="div"
v-bind="dragOptions"
@start="startDragLayout"
@end="finishDragLayout"
group="preview"
>
<div v-for="(element, index) in layout" :key="index">
// ...
<component :is="element.component" :dynamicStyle="element.dynamicStyle"></component>
</div>
</draggable>
</template>
<script>
export default {
model: {
prop: "jsonData",
event: "changePageInfo",
},
props: {
// 页面初始化数据
data: {
type: Array,
default: () => [],
},
},
data() {
return {
layout: []
}
},
computed: {
// 主要是定义一些属性
dragOptions() {
return {
animation: 200, // 动画执行时间
group: "preview", // 这个 group 的作用是,设置渲染区域的 group 和左边组件列表的 group 相同,在同一 group 中,即可进行克隆
disabled: false,
ghostClass: "ghost", // 组件拖动还未放下的样式
};
},
},
// ... 其他实现细节忽略
watch: {
// ...
}
}
</script>
实现 v-model,监听 layout 是否变更,然后派发 changePageInfo 事件即可实现 v-model。
<draggable></draggable>
标签是 Vue.Draggable (opens new window) 封装好的组件,只要把我们的布局数组 layout 跟内部进行判定,即可实现拖拽和 layout 数据更新。
而<draggable></draggable>
标签内部通过一个 v-for
循环包裹,结合 Vue 动态组件 <component :is="" />
即可实现组件的展示。
注:@start
、@end
等事件的绑定,函数的参数里面有新旧索引等重要信息可利用。
# 克隆
h5-editor 组件使用方式:
<h5-editor v-model="jsonData" :data="data"></h5-editor>
<draggable
class="all-coms__box dragArea list-group"
:list="baseComponentsData"
:group="{ name: 'preview', pull: 'clone', put: false }"
:clone="clone"
:sort="false"
@end="finishClone"
>
</draggable>
克隆组件跟拖拽组件多了两个设置属性:
- group:设置组别,组别跟预览区域的组别一样,都是 preview;
- sort:禁止自身列表重新排序。
# 显示对应的样式修改组件
在中间预览区域点击一个组件后,右边样式修改区域会显示对应的组件。这个逻辑实现比较简单,因为每个组件都有对应的索引,通过对应索引显示对应组件即可,结合 Vue 动态组件 <component :is="" />
即可实现组件的展示。
# 修改对应的渲染组件样式
当样式修改组件向上派发事件 changeStyle,父组件 h5-editor 就可以监听到事件触发和携带新的样式对象,然后通过修改 layout 对应索引的 dynamicStyle 属性值($set()
触发),即可修改对应渲染组件样式。